#include "coid/svc/coidsvc.h"

//{client 
#include "coid/comm/binstream/stlstream.h"
//}client

#include "string.h"
#include <stdlib.h>

//{client 
struct cMapImage
{
	std::string location;
	float minLat;
	float minLon;
	float maxLat;
	float maxLon;
	int coorX;
	int coorY;
	int zoom;
	
	friend binstream & operator << ( binstream & out, const cMapImage & x ) 	
	{ 
		return out << x.location << x.minLat << x.minLon << x.maxLat << x.maxLon << x.coorX << x.coorY << x.zoom; 
	};

	friend binstream & operator >> ( binstream & in, cMapImage & x ) 
	{
		return in >> x.location >> x.minLat >> x.minLon >> x.maxLat >> x.maxLon >> x.coorX >> x.coorY >> x.zoom;      /// notice the FIFO order (first in, first out)
    };

	friend metastream& operator << ( metastream& m, const cMapImage & x )
    {
        MSTRUCT_OPEN(m,"mapImage");
		MM(m,"location",x.location);
		MM(m,"minLat",x.minLat);
		MM(m,"minLon",x.minLon);
		MM(m,"maxLat",x.maxLat);
		MM(m,"maxLon",x.maxLon);
		MM(m,"coorX",x.coorX);
		MM(m,"coorY",x.coorY);
		MM(m,"zoom",x.zoom);
		MSTRUCT_CLOSE(m);
    }
};
//}client

//{client 
struct cConfiguration
{
	int imageHeight;
	int imageWidth;
	int maxHorizontalImagesCount;
	int maxVerticalImagesCount;
	int minZoom;
	int maxZoom;
	int actualZoom;
	cMapImage startImage;
	
	friend binstream & operator << ( binstream & out, const cConfiguration & x ) 	
	{ 
		return out << x.imageHeight << x.imageWidth << x.maxHorizontalImagesCount << x.maxVerticalImagesCount << x.minZoom << x.maxZoom << x.actualZoom << x.startImage; 
	};

	friend binstream & operator >> ( binstream & in, cConfiguration & x ) 
	{
		return in >> x.imageHeight >> x.imageWidth >> x.maxHorizontalImagesCount >> x.maxVerticalImagesCount >> x.minZoom >> x.maxZoom >> x.actualZoom >> x.startImage;      /// notice the FIFO order (first in, first out)
    };

	friend metastream& operator << ( metastream& m, const cConfiguration & x )
    {
        MSTRUCT_OPEN(m,"configuration");
		MM(m,"imageHeight",x.imageHeight);
		MM(m,"imageWidth",x.imageWidth);	
		MM(m,"maxHorizontalImagesCount",x.maxHorizontalImagesCount);
		MM(m,"maxVerticalImagesCount",x.maxVerticalImagesCount);
		MM(m,"minZoom",x.minZoom);
		MM(m,"maxZoom",x.maxZoom);
		MM(m,"actualZoom",x.actualZoom);
		MM(m,"startImage",x.startImage);
		MSTRUCT_CLOSE(m);
    }
};
//}client

//{client 
struct cImagePosition
{
	int cX;
	int cY;
	int zoom;
	float longitude;
	float latitude;
	
	friend binstream & operator << ( binstream & out, const cImagePosition & x ) 	
	{ 
		return out << x.cX << x.cY << x.zoom << x.longitude << x.latitude; 
	};

	friend binstream & operator >> ( binstream & in, cImagePosition & x ) 
	{
		return in >> x.cX >> x.cY >> x.zoom >> x.longitude >> x.latitude;      /// notice the FIFO order (first in, first out)
    };

	friend metastream& operator << ( metastream& m, const cImagePosition & x )
    {
        MSTRUCT_OPEN(m,"imagePosition");
		MM(m,"cX",x.cX);
		MM(m,"cY",x.cY);
		MM(m,"zoom",x.zoom);
		MM(m,"longitude",x.longitude);
		MM(m,"latitude",x.latitude);
		MSTRUCT_CLOSE(m);
    }

};
//}client


class maps
{
	cConfiguration config;

	float get_lat(int coorY);
	float get_lon(int coorX);
	float get_dif_lat();
	float get_dif_lon();
	int get_coorX(float lon);
	int get_coorY(float lat);
	int get_max_X(int zoom);
	int get_max_Y(int zoom);
	int get_image_height(int zoom);
	int get_image_width(int zoom);
	int get_zoom();


public:
	maps();

	~maps();

	net_fnc_s net_meta opcd accept_connect( int start_lat, int start_lon, int start_zoom, net_out cConfiguration & configuration);

	net_fnc net_meta opcd get_image_by_XY(net_in cImagePosition & imagePosition, net_out cMapImage & imageOut);

	net_fnc net_meta opcd get_image_by_lon_lat(net_in cImagePosition & imagePosition, net_out cMapImage & imageOut);

	net_fnc net_meta opcd change_zoom( net_in cImagePosition & imagePosition, net_out cConfiguration & configuration);

};